<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Carbon\Carbon;

/**
 * 合同模型
 * 管理员工劳动合同信息
 */
class Contract extends Model
{
    use HasFactory;

    /**
     * 表名
     */
    protected $table = 'contracts';

    /**
     * 可填充字段
     */
    protected $fillable = [
        'employee_id',
        'employee_name',
        'employee_number',
        'contract_number',
        'contract_type',
        'contract_category',
        'start_date',
        'end_date',
        'contract_period_months',
        'is_open_ended',
        'monthly_salary',
        'annual_salary',
        'salary_currency',
        'salary_grade',
        'benefits',
        'allowances',
        'insurance',
        'position',
        'department',
        'work_location',
        'working_hours',
        'probation_period',
        'responsibilities',
        'confidentiality_clause',
        'non_compete_clause',
        'termination_clause',
        'other_terms',
        'is_renewable',
        'max_renewals',
        'renewal_count',
        'renewal_status',
        'reminder_days',
        'reminder_sent',
        'last_reminder_date',
        'signed_by_employee',
        'signed_by_employee_date',
        'signed_by_company',
        'signed_by_company_date',
        'witness',
        'witness_date',
        'approved_by',
        'approved_at',
        'approval_notes',
        'status',
        'termination_date',
        'termination_reason',
        'terminated_by',
        'attachments',
        'custom_fields',
        'notes',
        'version',
        'is_latest',
    ];

    /**
     * 字段类型转换
     */
    protected $casts = [
        'start_date' => 'date',
        'end_date' => 'date',
        'signed_by_employee_date' => 'date',
        'signed_by_company_date' => 'date',
        'witness_date' => 'date',
        'approved_at' => 'date',
        'termination_date' => 'date',
        'last_reminder_date' => 'date',
        'is_open_ended' => 'boolean',
        'is_renewable' => 'boolean',
        'reminder_sent' => 'boolean',
        'is_latest' => 'boolean',
        'contract_period_months' => 'integer',
        'max_renewals' => 'integer',
        'renewal_count' => 'integer',
        'reminder_days' => 'integer',
        'monthly_salary' => 'decimal:2',
        'annual_salary' => 'decimal:2',
        'benefits' => 'array',
        'allowances' => 'array',
        'insurance' => 'array',
        'working_hours' => 'array',
        'attachments' => 'array',
        'custom_fields' => 'array',
        'version' => 'integer',
    ];

    /**
     * 日期字段
     */
    protected $dates = [
        'start_date',
        'end_date',
        'signed_by_employee_date',
        'signed_by_company_date',
        'witness_date',
        'approved_at',
        'termination_date',
        'last_reminder_date',
        'created_at',
        'updated_at',
    ];

    // ============ 常量定义 ============

    public const TYPE_LABOR = 'labor';
    public const TYPE_SERVICE = 'service';
    public const TYPE_CONSULTANCY = 'consultancy';
    public const TYPE_TRAINING = 'training';

    public const CATEGORY_FORMAL = 'formal';
    public const CATEGORY_PROBATION = 'probation';
    public const CATEGORY_FIXED_TERM = 'fixed_term';
    public const CATEGORY_INDEFINITE = 'indefinite';

    public const STATUS_DRAFT = 'draft';
    public const STATUS_ACTIVE = 'active';
    public const STATUS_TERMINATED = 'terminated';
    public const STATUS_EXPIRED = 'expired';
    public const STATUS_SUSPENDED = 'suspended';

    public const RENEWAL_ACTIVE = 'active';
    public const RENEWAL_RENEWED = 'renewed';
    public const RENEWAL_NOT_RENEWED = 'not_renewed';
    public const RENEWAL_EXPIRED = 'expired';

    // ============ 关联关系 ============

    /**
     * 关联员工
     */
    public function employee(): BelongsTo
    {
        return $this->belongsTo(Employee::class);
    }

    /**
     * 关联合同续约记录
     */
    public function renewals(): HasMany
    {
        return $this->hasMany(ContractRenewal::class)->orderBy('renewal_number');
    }

    /**
     * 关联合同调整记录
     */
    public function adjustments(): HasMany
    {
        return $this->hasMany(ContractAdjustment::class)->orderBy('effective_date', 'desc');
    }

    // ============ 访问器 ============

    /**
     * 获取合同类型标签
     */
    public function getContractTypeLabelAttribute(): string
    {
        return match($this->contract_type) {
            self::TYPE_LABOR => '劳动合同',
            self::TYPE_SERVICE => '服务合同',
            self::TYPE_CONSULTANCY => '咨询合同',
            self::TYPE_TRAINING => '培训合同',
            default => $this->contract_type ?? '未知'
        };
    }

    /**
     * 获取合同类别标签
     */
    public function getContractCategoryLabelAttribute(): string
    {
        return match($this->contract_category) {
            self::CATEGORY_FORMAL => '正式合同',
            self::CATEGORY_PROBATION => '试用合同',
            self::CATEGORY_FIXED_TERM => '固定期限',
            self::CATEGORY_INDEFINITE => '无固定期限',
            default => $this->contract_category ?? '未知'
        };
    }

    /**
     * 获取合同状态标签
     */
    public function getStatusLabelAttribute(): string
    {
        return match($this->status) {
            self::STATUS_DRAFT => '草稿',
            self::STATUS_ACTIVE => '生效中',
            self::STATUS_TERMINATED => '已终止',
            self::STATUS_EXPIRED => '已到期',
            self::STATUS_SUSPENDED => '已暂停',
            default => $this->status ?? '未知'
        };
    }

    /**
     * 获取续约状态标签
     */
    public function getRenewalStatusLabelAttribute(): string
    {
        return match($this->renewal_status) {
            self::RENEWAL_ACTIVE => '有效',
            self::RENEWAL_RENEWED => '已续约',
            self::RENEWAL_NOT_RENEWED => '不续约',
            self::RENEWAL_EXPIRED => '已过期',
            default => $this->renewal_status ?? '未知'
        };
    }

    /**
     * 获取合同期限
     */
    public function getContractPeriodAttribute(): string
    {
        if ($this->is_open_ended) {
            return '无固定期限';
        }

        if ($this->contract_period_months) {
            $years = floor($this->contract_period_months / 12);
            $months = $this->contract_period_months % 12;

            if ($years > 0 && $months > 0) {
                return "{$years}年{$months}个月";
            } elseif ($years > 0) {
                return "{$years}年";
            } else {
                return "{$months}个月";
            }
        }

        return '未设置';
    }

    /**
     * 获取薪资信息
     */
    public function getSalaryInfoAttribute(): string
    {
        if ($this->monthly_salary) {
            return number_format($this->monthly_salary) . ' 元/月';
        }

        if ($this->annual_salary) {
            return number_format($this->annual_salary) . ' 元/年';
        }

        return '未设置';
    }

    /**
     * 获取到期天数
     */
    public function getDaysUntilExpirationAttribute(): ?int
    {
        if (!$this->end_date || $this->is_open_ended) {
            return null;
        }

        return now()->diffInDays($this->end_date, false);
    }

    /**
     * 获取是否即将到期
     */
    public function getIsExpiringSoonAttribute(): bool
    {
        $days = $this->days_until_expiration;
        return $days !== null && $days <= $this->reminder_days && $days >= 0;
    }

    /**
     * 获取是否已过期
     */
    public function getIsExpiredAttribute(): bool
    {
        if ($this->is_open_ended) {
            return false;
        }

        return $this->end_date && now()->isAfter($this->end_date);
    }

    /**
     * 获取是否需要提醒
     */
    public function getNeedsReminderAttribute(): bool
    {
        // 只有活跃状态的合同且未发送提醒且即将到期才需要提醒
        return $this->status === self::STATUS_ACTIVE
            && !$this->reminder_sent
            && $this->is_expiring_soon
            && $this->renewal_status === self::RENEWAL_ACTIVE;
    }

    // ============ 作用域 ============

    /**
     * 生效中作用域
     */
    public function scopeActive($query)
    {
        return $query->where('status', self::STATUS_ACTIVE);
    }

    /**
     * 最新版本作用域
     */
    public function scopeLatest($query)
    {
        return $query->where('is_latest', true);
    }

    /**
     * 即将到期作用域
     */
    public function scopeExpiringSoon($query, $days = 30)
    {
        return $query->where('status', self::STATUS_ACTIVE)
                    ->where('is_open_ended', false)
                    ->where('end_date', '<=', now()->addDays($days))
                    ->where('end_date', '>=', now());
    }

    /**
     * 已过期作用域
     */
    public function scopeExpired($query)
    {
        return $query->where('status', self::STATUS_ACTIVE)
                    ->where('is_open_ended', false)
                    ->where('end_date', '<', now());
    }

    /**
     * 需要提醒作用域
     */
    public function scopeNeedsReminder($query)
    {
        return $query->where('status', self::STATUS_ACTIVE)
                    ->where('reminder_sent', false)
                    ->where('renewal_status', self::RENEWAL_ACTIVE)
                    ->whereRaw('DATEDIFF(end_date, CURDATE()) <= reminder_days')
                    ->whereRaw('DATEDIFF(end_date, CURDATE()) >= 0');
    }

    /**
     * 按合同类型筛选作用域
     */
    public function scopeByType($query, $type)
    {
        return $query->where('contract_type', $type);
    }

    /**
     * 按员工筛选作用域
     */
    public function scopeByEmployee($query, $employeeId)
    {
        return $query->where('employee_id', $employeeId);
    }

    /**
     * 可续约作用域
     */
    public function scopeRenewable($query)
    {
        return $query->where('is_renewable', true)
                    ->where(function ($query) {
                        $query->whereNull('max_renewals')
                              ->orWhereRaw('renewal_count < max_renewals');
                    });
    }

    // ============ 业务方法 ============

    /**
     * 激活合同
     */
    public function activate(): bool
    {
        $this->status = self::STATUS_ACTIVE;
        return $this->save();
    }

    /**
     * 终止合同
     */
    public function terminate(string $reason, string $terminatedBy): bool
    {
        $this->status = self::STATUS_TERMINATED;
        $this->termination_date = now();
        $this->termination_reason = $reason;
        $this->terminated_by = $terminatedBy;

        return $this->save();
    }

    /**
     * 暂停合同
     */
    public function suspend(): bool
    {
        $this->status = self::STATUS_SUSPENDED;
        return $this->save();
    }

    /**
     * 续约合同
     */
    public function renew(array $renewalData): ContractRenewal
    {
        $renewal = ContractRenewal::create(array_merge($renewalData, [
            'contract_id' => $this->id,
            'employee_id' => $this->employee_id,
            'original_contract_number' => $this->contract_number,
            'renewal_number' => $this->renewal_count + 1,
        ]));

        $this->renewal_count++;
        $this->renewal_status = self::RENEWAL_RENEWED;
        $this->save();

        return $renewal;
    }

    /**
     * 设置不续约
     */
    public function setNotRenewable(): bool
    {
        $this->renewal_status = self::RENEWAL_NOT_RENEWED;
        return $this->save();
    }

    /**
     * 发送到期提醒
     */
    public function sendReminder(): bool
    {
        $this->reminder_sent = true;
        $this->last_reminder_date = now();
        return $this->save();
    }

    /**
     * 重置提醒状态
     */
    public function resetReminder(): bool
    {
        $this->reminder_sent = false;
        $this->last_reminder_date = null;
        return $this->save();
    }

    /**
     * 创建新版本
     */
    public function createNewVersion(): self
    {
        // 将当前版本设为非最新
        $this->is_latest = false;
        $this->save();

        // 创建新版本
        $newContract = $this->replicate();
        $newContract->version = $this->version + 1;
        $newContract->is_latest = true;
        $newContract->status = self::STATUS_DRAFT;
        $newContract->save();

        return $newContract;
    }

    // ============ 静态方法 ============

    /**
     * 获取合同类型选项
     */
    public static function getContractTypeOptions(): array
    {
        return [
            self::TYPE_LABOR => '劳动合同',
            self::TYPE_SERVICE => '服务合同',
            self::TYPE_CONSULTANCY => '咨询合同',
            self::TYPE_TRAINING => '培训合同',
        ];
    }

    /**
     * 获取合同类别选项
     */
    public static function getContractCategoryOptions(): array
    {
        return [
            self::CATEGORY_FORMAL => '正式合同',
            self::CATEGORY_PROBATION => '试用合同',
            self::CATEGORY_FIXED_TERM => '固定期限',
            self::CATEGORY_INDEFINITE => '无固定期限',
        ];
    }

    /**
     * 获取合同状态选项
     */
    public static function getStatusOptions(): array
    {
        return [
            self::STATUS_DRAFT => '草稿',
            self::STATUS_ACTIVE => '生效中',
            self::STATUS_TERMINATED => '已终止',
            self::STATUS_EXPIRED => '已到期',
            self::STATUS_SUSPENDED => '已暂停',
        ];
    }

    /**
     * 生成合同编号
     */
    public static function generateContractNumber(): string
    {
        $year = date('Y');
        $prefix = 'CON' . $year;

        $lastContract = self::where('contract_number', 'like', $prefix . '%')
            ->orderBy('contract_number', 'desc')
            ->first();

        if ($lastContract) {
            $lastNumber = intval(substr($lastContract->contract_number, -6));
            $newNumber = str_pad($lastNumber + 1, 6, '0', STR_PAD_LEFT);
        } else {
            $newNumber = '000001';
        }

        return $prefix . $newNumber;
    }

    /**
     * 获取即将到期的合同
     */
    public static function getExpiringContracts($days = 30): \Illuminate\Database\Eloquent\Collection
    {
        return self::expiringSoon($days)->get();
    }

    /**
     * 发送批量提醒
     */
    public static function sendBulkReminders(): int
    {
        $contracts = self::needsReminder()->get();
        $count = 0;

        foreach ($contracts as $contract) {
            // 这里可以集成邮件或消息系统
            // 暂时只标记为已发送
            $contract->sendReminder();
            $count++;
        }

        return $count;
    }

    /**
     * 验证合同数据
     */
    public static function validateContractData(array $data): array
    {
        $errors = [];

        // 必填字段验证
        $requiredFields = ['employee_id', 'contract_type', 'start_date'];
        foreach ($requiredFields as $field) {
            if (empty($data[$field])) {
                $errors[] = "{$field} 字段不能为空";
            }
        }

        // 合同类型验证
        $validTypes = array_keys(self::getContractTypeOptions());
        if (!empty($data['contract_type']) && !in_array($data['contract_type'], $validTypes)) {
            $errors[] = "无效的合同类型";
        }

        // 合同类别验证
        $validCategories = array_keys(self::getContractCategoryOptions());
        if (!empty($data['contract_category']) && !in_array($data['contract_category'], $validCategories)) {
            $errors[] = "无效的合同类别";
        }

        // 状态验证
        $validStatuses = array_keys(self::getStatusOptions());
        if (!empty($data['status']) && !in_array($data['status'], $validStatuses)) {
            $errors[] = "无效的状态";
        }

        // 薪资验证
        if (!empty($data['monthly_salary']) && (!is_numeric($data['monthly_salary']) || $data['monthly_salary'] <= 0)) {
            $errors[] = "月薪必须是有效的正数";
        }

        if (!empty($data['annual_salary']) && (!is_numeric($data['annual_salary']) || $data['annual_salary'] <= 0)) {
            $errors[] = "年薪必须是有效的正数";
        }

        // 时间验证
        if (!empty($data['start_date']) && !empty($data['end_date'])) {
            $startDate = strtotime($data['start_date']);
            $endDate = strtotime($data['end_date']);

            if ($startDate && $endDate && $startDate >= $endDate) {
                $errors[] = "结束日期必须晚于开始日期";
            }
        }

        // 提醒天数验证
        if (!empty($data['reminder_days']) && (!is_numeric($data['reminder_days']) || $data['reminder_days'] < 0)) {
            $errors[] = "提醒天数必须是有效的非负数";
        }

        return $errors;
    }
}
